
package com.hlkj.pay.controller.pay;
/*
 * Hlpay-Plus aggregate payment system.
 * Copyright (c) 2024-2025 Hlpay Team Copyright has the right of final interpretation.
 */

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import com.hlkj.framework.common.pojo.CommonResult;
import com.hlkj.framework.common.pojo.PageResult;
import com.hlkj.framework.common.util.collection.CollectionUtils;
import com.hlkj.framework.common.util.json.JsonUtils;
import com.hlkj.pay.app.merchant.IMerchantInfoAppService;
import com.hlkj.pay.app.pay.IProviderAppService;
import com.hlkj.pay.app.transfer.PayChannelDoToResp;
import com.hlkj.pay.app.transfer.PayWayDoToResp;
import com.hlkj.pay.app.transfer.ProviderDoToResp;
import com.hlkj.pay.common.PayResultCode;
import com.hlkj.pay.controller.BaseController;
import com.hlkj.pay.dto.merchant.ProviderChannelFeeConfigList;
import com.hlkj.pay.dto.pay.PayChannelQueryDto;
import com.hlkj.pay.dto.pay.ProviderQueryDto;
import com.hlkj.pay.enums.CommonEnum;
import com.hlkj.pay.infrastructure.model.merchant.MerchantConfigDO;
import com.hlkj.pay.infrastructure.model.pay.*;
import com.hlkj.pay.service.pay.IPayChannelService;
import com.hlkj.pay.service.pay.IPayWayService;
import com.hlkj.pay.service.pay.IProviderService;
import com.hlkj.pay.vo.common.req.DeleteCodeReq;
import com.hlkj.pay.vo.pay.req.ProviderChannelConfigReq;
import com.hlkj.pay.vo.pay.req.ProviderChannelFeeConfigReq;
import com.hlkj.pay.vo.pay.req.ProviderInfoReq;
import com.hlkj.pay.vo.pay.req.ProviderPageQueryReq;
import com.hlkj.pay.vo.pay.resp.*;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.dreamlu.mica.core.utils.BeanUtil;

/**
 * @author HlpayTeam
 * @date 2024/09/23 16:27
 */
@Tag(name = "服务商配置")
@RestController
@RequestMapping("/v1/pay/provider")
@Slf4j
@RequiredArgsConstructor
public class ProviderController extends BaseController {

    private final IProviderAppService providerAppService;

    private final IProviderService providerService;

    private final IPayWayService payWayService;

    private final IPayChannelService payChannelService;

    private final IMerchantInfoAppService merchantInfoAppService;

    @Operation(summary = "分页查询")
    @GetMapping("/page")
    CommonResult<PageResult<ProviderInfoResp>> queryProviderPage(@Validated ProviderPageQueryReq pageParam) {
        ProviderQueryDto payWayQueryDO = BeanUtil.copy(pageParam, ProviderQueryDto.class);
        payWayQueryDO.setLikeCode(pageParam.getCode());
        payWayQueryDO.setLikeName(pageParam.getName());
        payWayQueryDO.setLikeShortName(pageParam.getShorName());
        payWayQueryDO.setCode(null);
        payWayQueryDO.setName(null);
        payWayQueryDO.setShortName(null);
        PageResult<ProviderInfoDO> page = providerService.queryPage(payWayQueryDO);
        List<ProviderInfoDO> list = page.getList();
        if (CollectionUtils.isEmpty(list)) {
            return buildPageResult(page, Collections.emptyList());
        }
        return buildPageResult(page, ProviderDoToResp.INSTANCE.providerInfoRespList(list));
    }

    @Operation(summary = "服务商渠道")
    @GetMapping("/channel")
    CommonResult<List<PayChannelListResp>> queryPayChannelList(@RequestParam("code") String code) {
        List<PayChannelDO> payWayList = payChannelService.queryList(new PayChannelQueryDto());
        if (CollectionUtils.isEmpty(payWayList)) {
            return CommonResult.success(Collections.emptyList());
        }
        List<PayChannelListResp> payChannelListResps = PayChannelDoToResp.INSTANCE.payChannelListRespList(payWayList);
        List<ProviderChannelConfigDO> providerChannelConfigList = providerService.queryConfigList(code);

        Map<String, ProviderChannelConfigDO> providerChannelConfigMap = providerChannelConfigList.stream()
                .collect(Collectors.toMap(providerChannelConfigDO -> providerChannelConfigDO.getChannelCode(), Function.identity(), (t1, t2) -> t1));
        payChannelListResps.stream().forEach(payChannelListResp -> {
            ProviderChannelConfigDO providerChannelConfigDO = providerChannelConfigMap.get(payChannelListResp.getCode());
            if (providerChannelConfigDO != null) {
                payChannelListResp.setStatus(providerChannelConfigDO.getStatus());
            }
            else {
                payChannelListResp.setStatus(CommonEnum.YES_NO_TYPE.NO.getCode());
            }
        });
        return CommonResult.success(payChannelListResps);
    }

    @Operation(summary = "不分页查询")
    @GetMapping("")
    CommonResult<List<ProviderInfoResp>> queryProviderList(@Validated ProviderPageQueryReq pageParam) {
        ProviderQueryDto payWayQueryDO = BeanUtil.copy(pageParam, ProviderQueryDto.class);
        payWayQueryDO.setLikeCode(pageParam.getCode());
        payWayQueryDO.setLikeName(pageParam.getName());
        payWayQueryDO.setCode(null);
        payWayQueryDO.setName(null);

        // 代理商过滤
        if(StrUtil.isNotEmpty(pageParam.getSn())){
            MerchantConfigDO merchantConfigDO = merchantInfoAppService.queryConfig(pageParam.getSn());
            if(merchantConfigDO != null && CollUtil.isNotEmpty(merchantConfigDO.getProviderCodeList())){
                payWayQueryDO.setCodes(merchantConfigDO.getProviderCodeList());
            }
        }

        List<ProviderInfoDO> payWayList = providerService.queryList(payWayQueryDO);
        if (CollectionUtils.isEmpty(payWayList)) {
            return CommonResult.success(Collections.emptyList());
        }
        return CommonResult.success(ProviderDoToResp.INSTANCE.providerInfoRespList(payWayList));
    }

    @Operation(summary = "服务商详情")
    @GetMapping("/detail")
    CommonResult<ProviderInfoResp> detail(@RequestParam("code") String code) {
        ProviderInfoDO providerInfoDO = providerService.queryByCode(code);
        if (providerInfoDO == null) {
            return CommonResult.success(null);
        }
        ProviderInfoResp providerInfoResp = ProviderDoToResp.INSTANCE.providerInfoResp(providerInfoDO);
        List<ProviderChannelConfigDO> providerChannelConfigList = providerService.queryConfigList(code);
        if (CollectionUtils.isEmpty(providerChannelConfigList)) {
            return CommonResult.success(providerInfoResp);
        }
        providerInfoResp.setChannelCodes(providerChannelConfigList.stream().map(providerChannelConfigDO -> providerChannelConfigDO.getChannelCode()).collect(Collectors.toList()));
        return CommonResult.success(providerInfoResp);
    }

    @Operation(summary = "新增服务商")
    @PostMapping("")
    CommonResult<String> saveProviderInfo(@Validated @RequestBody ProviderInfoReq providerInfoReq) {
        return providerAppService.saveProviderInfo(providerInfoReq);
    }

    @Operation(summary = "更新服务商")
    @PutMapping("")
    CommonResult<Void> updateProviderInfo(@Validated @RequestBody ProviderInfoReq providerInfoReq) {
        return providerAppService.updateProviderInfo(providerInfoReq);
    }

    @Operation(summary = "删除服务商")
    @DeleteMapping("")
    CommonResult<Void> delProviderInfo(@Validated @RequestBody DeleteCodeReq deleteCodeReq) {
        return providerAppService.delProviderInfo(deleteCodeReq.getCode());
    }

    @Operation(summary = "获取服务商配置")
    @GetMapping("/config")
    CommonResult<ProviderChannelConfigResp> queryProviderConfig(@RequestParam(name = "providerCode") String providerCode, @RequestParam(name = "channelCode") String channelCode) {
        ProviderChannelConfigDO providerChannelConfigDO = providerService.queryConfig(providerCode, channelCode);
        if (providerChannelConfigDO == null) {
            return CommonResult.success(new ProviderChannelConfigResp());
        }

        ProviderChannelConfigResp providerChannelConfigResp = ProviderDoToResp.INSTANCE.providerChannelConfigResp(providerChannelConfigDO);
        providerChannelConfigResp.setWechatMiniIdList(providerChannelConfigDO.getWechatMiniIdList());
        providerChannelConfigResp.setWechatPubIdList(providerChannelConfigDO.getWechatPubIdList());
        providerChannelConfigResp.setParamsConfigValue(JsonUtils.parseObject(providerChannelConfigDO.getParamsConfig(), Map.class));
        return CommonResult.success(providerChannelConfigResp);
    }

    @Operation(summary = "保存服务商配置")
    @PostMapping("/config")
    CommonResult<Void> saveProviderConfig(@Validated @RequestBody ProviderChannelConfigReq providerChannelConfigReq) {
        return providerAppService.saveConfig(providerChannelConfigReq);
    }

    @Operation(summary = "获取服务商费率配置")
    @GetMapping("/feeConfig")
    CommonResult<List<ProviderChannelFeeConfigResp>> queryProviderFeeConfig(@RequestParam(name = "providerCode") String providerCode,
            @RequestParam(name = "channelCode") String channelCode) {
        PayChannelDO payChannelDO = payChannelService.queryByCode(channelCode);
        List<String> payWayCodes = payChannelDO.getPayWapCodeList();
        if (CollectionUtils.isEmpty(payWayCodes)) {
            return CommonResult.error(PayResultCode.PAY_CHANNEL_WAY_NOT_ERROR);
        }
        List<PayWayDO> payWayList = payWayService.queryByCodes(payWayCodes);
        List<ProviderChannelFeeConfigDO> providerChannelFeeConfigList = providerService.queryFeeConfig(providerCode, channelCode);
        if (CollectionUtils.isEmpty(providerChannelFeeConfigList)) {
            providerChannelFeeConfigList = new ArrayList<>();
        }
        Map<String, ProviderChannelFeeConfigDO> providerChannelFeeConfigMap = providerChannelFeeConfigList.stream()
                .collect(Collectors.toMap(providerChannelFeeConfigDO -> providerChannelFeeConfigDO.getPayWayCode(), Function.identity(), (t1, t2) -> t1));
        List<PayWayResp> payWayResps = PayWayDoToResp.INSTANCE.payWayRespList(payWayList);
        List<ProviderChannelFeeConfigResp> providerChannelFeeConfigResps = new ArrayList<>();
        payWayResps.stream().forEach(payWayResp -> {
            ProviderChannelFeeConfigDO providerChannelFeeConfigDO = providerChannelFeeConfigMap.get(payWayResp.getCode());
            // 没有配置 填充默认值
            if (providerChannelFeeConfigDO == null) {
                providerChannelFeeConfigDO = new ProviderChannelFeeConfigDO();
                providerChannelFeeConfigDO.setProviderCode(providerCode);
                providerChannelFeeConfigDO.setPayWayCode(payWayResp.getCode());
                providerChannelFeeConfigDO.setStatus(CommonEnum.YES_NO_TYPE.NO.getCode());
                providerChannelFeeConfigDO.setSeniorFeeType(payWayResp.getSeniorFeeType());
                providerChannelFeeConfigDO.setApplyType(payWayResp.getApplyType());
                providerChannelFeeConfigDO.setStepFeeType(payWayResp.getStepFeeType());
            }
            ProviderChannelFeeConfigResp providerChannelFeeConfigResp = ProviderDoToResp.INSTANCE.providerChannelFeeConfigResp(providerChannelFeeConfigDO);
            providerChannelFeeConfigResp.setPayWay(payWayResp);
            providerChannelFeeConfigResps.add(providerChannelFeeConfigResp);

        });
        return CommonResult.success(providerChannelFeeConfigResps);
    }

    @Operation(summary = "保存服务商费率配置")
    @PostMapping("/feeConfig")
    CommonResult<Void> saveProviderFeeConfig(@RequestBody ProviderChannelFeeConfigReq providerChannelConfigReq) {
        List<ProviderChannelFeeConfigList> channelFeeConfigLists = providerChannelConfigReq.getProviderChannelFeeConfigList().stream()
                .filter(providerChannelFeeConfigList -> CommonEnum.YES_NO_TYPE.YES.getCode()
                        .equals(providerChannelFeeConfigList.getStatus())).collect(Collectors.toList());
        providerChannelConfigReq.setProviderChannelFeeConfigList(channelFeeConfigLists);
        return providerAppService.saveFeeConfig(providerChannelConfigReq);
    }

}
